package com.atguigu.tingshu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ApplicationContext;

/**
 * ServiceAlbumApplication
 * <p>
 * 注解 @SpringBootApplication 表示这是一个Spring Boot应用程序，自动配置Spring Boot。
 * 注解 @EnableDiscoveryClient 表示启用服务发现功能，用于向注册中心注册服务。
 * 注解 @EnableFeignClients 表示启用Feign客户端功能，用于调用其他服务。
 * <p>
 * SSM框架：
 * - SpringMVC（表现层）：负责处理用户请求和响应，包含Model（模型/实体类）、View（视图/HTML页面/JSON响应）和Controller（控制器）。
 * - Spring（业务逻辑层/服务层）：处理业务逻辑，包含Service组件。
 * - MyBatis（持久化层）：负责与数据库交互，包含Mapper组件。
 *
 * @author Taeyang
 * @date 2025-04-22
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceAlbumApplication {

    // private final MinioConstantProperties minioConstantProperties;

    // @Autowired
    // public ServiceAlbumApplication(MinioConstantProperties minioConstantProperties, RedissonClient redissonClient) {
    // this.redissonClient = redissonClient;
    // this.minioConstantProperties = minioConstantProperties;
    // }

    /**
     * 项目启动时，启动类的@SpringBootApplication注解中的@ComponentScan扫描到启动类时，这个方法就会被放到容器中，后续项目中的任何地方想要用就可以直接使用了。
     *
     * @return RestTemplate 对象
     */
    // @Bean
    // public RestTemplate restTemplateTest() {
    //     return new RestTemplate();
    // }


    /**
     * 初始化创建Minio客户端对象
     *
     * @return Minio客户端对象
     */
    // @Bean
    // public MinioClient minioClient() {
    //     // 初始化Minio的客户端对象
    //     return MinioClient.builder()
    //             // MinIO服务端地址和端口
    //             .endpoint(minioConstantProperties.getEndpointUrl())
    //             // 访问密钥和密钥
    //             .credentials(minioConstantProperties.getAccessKey(), minioConstantProperties.getSecreKey())
    //             .build();
    // }

    /**
     * 主函数，用于启动Spring Boot应用程序。
     * <p>
     * SpringBoot是什么？工具
     * <p>
     * SSM框架（SpringMVC + Spring + MyBatis）两大核心问题：
     * 1. 配置
     * - spring.xml、springmvc.xml、spring-mybatis.xml、web.xml...
     * - 并且每个配置文件中大多都是在配置大量的bean <bean id="" name="" class=""></bean>
     * 2. jar包：坐标、名称、版本（敏感）
     * - jar太多，导致配置文件过长，维护麻烦
     * - 版本之间的版本不兼容，导致项目运行报错
     * <p>
     * SpringBoot对SSM框架的优化
     * 1. 配置：自动装配/自动配置
     * - 通过@SpringBootApplication注解实现
     * 2. jar包：起步依赖，本质上是对pom文件优化
     * - 引入父工程（官方确定了所有用得到的用不到的jar包的版本号）
     * - 使用Maven依赖传递（解决每个pom文件中jar包引入都很多）
     *
     * @param args 命令行（JVM）参数，传递给Spring Boot应用程序的启动参数，构建一个怎样的java虚拟机。
     */
    public static void main(String[] args) {
        // 启动 Spring Boot 应用程序（启动了一个进程），指定主应用程序类为ServiceAlbumApplication
        // 1：创建了一个容器（Spring）：装Bean
        // 2: 识别 @SpringBootApplication 注解，自动配置 Spring Boot 应用程序
        //    @SpringBootConfiguration：标识启动类是一个配置类
        //      - @Configuration：该类是一个配置类，类中的某些方法或者属性加上@Bean，类中的这些方法或者属性是Bean被放到容器中，粗暴方式区分 @Component：整个类对象是一个Bean
        //    @EnableAutoConfiguration：自动配置（尝试使用反射技术对spring官方在自动配置类包下定义的全部可能用到的配置类进行加载，加载成功的放入容器，失败的放弃尝试加载下一个）
        //      - @AutoConfigurationPackage：加载一个自动配置的包
        //      - @Import({AutoConfigurationImportSelector.class})：自动配置导入选择器，存储的是类的全量限定名 @EnableAutoConfiguration 注解被识别到被扫描到时才会触发AutoConfigurationImportSelector.class类的字节码文件加载，没有识别到就不会被加载
        //    @ComponentScan：扫描当前包及子包下所有类（不同模块下被依赖并且在其模块中的文件夹路径和该启动类所在模块的所在路径相同也会被扫描，不同路径的需要在启动类上手动指定扫描文件夹）
        //      - 扫描启动类所在的包下所有类的所有注解（只能扫到启动类，触发另外两个注解）
        //      - 扫描启动类所在包下子包中所有类的所有注解（自定义的Bean）：controller、service、mapper
        //
        // 拓展：@ConditionalOnMissingBean注解：当容器中没有指定Bean时，才会加载当前类，防止重复加载Bean
        ApplicationContext applicationContext =
            SpringApplication.run(ServiceAlbumApplication.class, args);
        System.out.println(applicationContext.getBean("redisTemplate"));
    }


}